#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include "buffer.h"

#define BUFFER_SIZE 10

void *produce(void *param);
void *consume(void *param);

int main(int argc, char **argv) {
	/*
	1. get command line arguments: time to sleep before terminating, number of producer threads, number of consumer threads
	2. initialize buffer
	3. create producer threads
	4. create consumer threads
	5. sleep
	6. exit
	*/
	int sleep_time;
	int num_producers;
	int num_consumers;
	buffer buff;
	pthread_t *producers;
	pthread_t *consumers;
	int i;

	if(argc != 4) {
		fprintf(stderr, "usage: buffer sleep_time producers consumers\n");
		exit(1);
	}
	sleep_time = atoi(argv[1]);
	num_producers = atoi(argv[2]);
	num_consumers = atoi(argv[3]);
	if(sleep_time <= 0 || num_producers <= 0 || num_consumers <= 0) {
		fprintf(stderr, "all values must be greater than 0\n");
		exit(1);
	}

	if(init_buffer(&buff, BUFFER_SIZE) < 0) {
		fprintf(stderr, "failed to initialize buffer\n");
		exit(1);
	}

	producers = (pthread_t*) malloc(num_producers*sizeof(*producers));
	for(i=0; i<num_producers; i++) {
		pthread_create(&(producers[i]), NULL, produce, &buff);
	}

	consumers = (pthread_t*) malloc(num_consumers*sizeof(*consumers));
	for(i=0; i<num_consumers; i++) {
		pthread_create(&(consumers[i]), NULL, consume, &buff);
	}

	sleep(sleep_time);

	destroy_buffer(&buff);
	free(producers);
	free(consumers);
	return 0;
}

void *produce(void *param) {
	buffer *buff;
	buffer_item item;

	buff = (buffer*) param;

	srand(time(NULL));
	while(1) {
		usleep(rand()%999999);
		//sleep(rand()%3);

		item = (buffer_item)rand();
		if(!buffer_insert(buff, item)) {
			printf("producer produced %d\n", (int)item);
		}
		else {
			fprintf(stderr, "error: producer failed to insert %d\n", (int)item);
		}
	}
}

void *consume(void *param) {
	buffer *buff;
	buffer_item item;

	buff = (buffer*) param;

	srand(time(NULL));
	while(1) {
		usleep(rand()%999999);
		//sleep(rand()%3);

		if(!buffer_remove(buff, &item)) {
			printf("consumer consumed %d\n", (int)item);
		}
		else {
			fprintf(stderr, "error: consumer failed to consume\n");
		}
	}
}
